﻿using System;
using System.Globalization;

namespace Microsoft.International.Formatters
{

    /// <summary>
    /// German (de-DE) formatter
    /// </summary>
    [FormatCultureInfoAttribute("de-DE")]
    internal sealed class DEStdFormatter : EuropeFormatter
    {

        /// <summary>
        /// Returns the Decimal value to String.
        /// </summary>
        /// <param name="num">Value to translate.</param>
        /// <returns>Returns the specified Decimal value to String.</returns>
        /// <remarks>Abstract method, must be implemented.</remarks>
        internal override String ConvertToLocalizedText(Decimal num)
        {
            String strMoins = String.Empty;
            Int32 value = (Int32)num; // TODO: Supprimer cette ligne
            if (value < 0)
            {
                strMoins = "weniger ";
                if (value == Int32.MinValue)
                {
                    strMoins += "zwei Milliarden ";
                    value += 2000000000;
                }
                value = Math.Abs(value);
            }

            return strMoins + BillionToString(value);
        }

        /// <summary>
        /// Convert units (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String UnitToString(Int32 value)
        {
            if (value > 9)
                return TenToString(value);

            String result = String.Empty;

            switch (value)
            {
                case 0: result = "null"; break;
                case 1: result = "eins"; break;
                case 2: result = "zwei"; break;
                case 3: result = "drei"; break;
                case 4: result = "vier"; break;
                case 5: result = "fünf"; break;
                case 6: result = "sechs"; break;
                case 7: result = "sieben"; break;
                case 8: result = "acht"; break;
                case 9: result = "neun"; break;
            }

            return result;
        }

        /// <summary>
        /// Get the singular value
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private String Singular(Int32 value)
        {
            String result = String.Empty;

            switch (value)
            {
                case 1: result = "ein"; break;
                case 6: result = "sech"; break;
                case 7: result = "sieb"; break;
                default: result = UnitToString(value); break;
            }

            return result;
        }

        /// <summary>
        /// Convert tens (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String TenToString(Int32 value)
        {
            if (value < 10)
                return UnitToString(value);
            else if (value > 99)
                return HundredToString(value);

            String result = String.Empty;

            if (value.Between(13, 19))
                result = String.Format(new CultureInfo("de-de"), "{0}zehn", Singular(value - 10));

            else if (value.Between(22, 29) | value.Between(32, 39) | value.Between(42, 49)
                        | value.Between(52, 59) | value.Between(62, 69) | value.Between(72, 79)
                        | value.Between(82, 89) | value.Between(92, 99))
                result = String.Format(new CultureInfo("de-de"), "{0}und{1}", UnitToString(value.GetUnit()), TenToString(value.GetTen()));

            else if (value.GetTen() > 10 & value.GetUnit() == 1)
                result = String.Format(new CultureInfo("de-de"), "einund{0}", TenToString(value.GetTen()));

            else switch (value)
                {
                    case 10: result = "zehn"; break;
                    case 11: result = "elf"; break;
                    case 12: result = "zwölf"; break;

                    case 20: result = "zwanzig"; break;
                    case 30: result = "dreißig"; break;
                    case 40: result = "vierzig"; break;
                    case 50: result = "fünfzig"; break;
                    case 60: result = "sechzig"; break;
                    case 70: result = "siebzig"; break;
                    case 80: result = "achtzig"; break;
                    case 90: result = "neunzig"; break;
                }

            return result;
        }

        /// <summary>
        /// Convert hundreds (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String HundredToString(Int32 value)
        {
            if (value < 100)
                return TenToString(value);
            else if (value > 999)
                return ThousandToString(value);

            Int32 reste = 0;
            Int32 centaine = System.Math.DivRem(value, 100, out reste);

            String strCentaine = "einhundert";
            if (centaine != 1)
                strCentaine = String.Format(new CultureInfo("de-de"), "{0}hundert", TenToString(centaine));

            if (reste != 0)
                strCentaine = String.Format(new CultureInfo("de-de"), "{0}{1}", strCentaine, TenToString(reste));

            return strCentaine;
        }

        /// <summary>
        /// Convert thousands (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String ThousandToString(Int32 value)
        {
            if (value < 1000)
                return HundredToString(value);
            else if (value > 999999)
                return MillionToString(value);

            Int32 reste = 0;
            Int32 millier = System.Math.DivRem(value, 1000, out reste);

            String strMillier = "eintausend";
            if (millier != 1)
                strMillier = String.Format(new CultureInfo("de-de"), "{0}tausend", TenToString(millier));

            if (reste != 0)
                strMillier = String.Format(new CultureInfo("de-de"), "{0}{1}", strMillier, TenToString(reste));

            return strMillier;
        }

        /// <summary>
        /// Convert millions (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String MillionToString(Int32 value)
        {
            if (value < 1000000)
                return HundredToString(value);
            else if (value > 999999999)
                return BillionToString(value);

            Int32 reste = 0;
            Int32 millions = System.Math.DivRem(value, 1000000, out reste);

            String strMillions = "eine Million";
            if (millions != 1)
                strMillions = String.Format(new CultureInfo("de-de"), "{0} Millionen", TenToString(millions));

            if (reste != 0)
                strMillions = String.Format(new CultureInfo("de-de"), "{0} {1}", strMillions, TenToString(reste));

            return strMillions;
        }

        /// <summary>
        /// Convert billions (Int32 format) to String format.
        /// </summary>
        /// <param name="value">Value to convert</param>
        /// <returns>Returns a text which represents the specified value</returns>
        private String BillionToString(Int32 value)
        {
            if (value < 1000000000)
                return MillionToString(value);

            Int32 reste = 0;
            Int32 milliard = System.Math.DivRem(value, 1000000000, out reste);

            String strMilliard = "eine Milliarde";
            if (milliard != 1)
                strMilliard = String.Format(new CultureInfo("de-de"), "{0} Milliarden", TenToString(milliard));

            if (reste != 0)
                strMilliard = String.Format(new CultureInfo("de-de"), "{0} {1}", strMilliard, TenToString(reste));

            return strMilliard;
        }

    }

}